# -*- coding: utf-8 -*-

from PyQt5.QtGui import QImage, QPainter
from PyQt5.QtCore import Qt

from flow.check.stack import Stack


class CheckedBackendProcessor(object):
    def __init__(self, src_folder, dst_folder):
        self.src_stack = Stack(src_folder)
        self.dst_stack = Stack(dst_folder)
        self.current_node = None
        self.current_image = None
        self.show_image = None
        self.current_label_points = list()

    @staticmethod
    def read_labeled_points(label_file_path):
        with open(label_file_path) as label_file:
            str_points = label_file.readlines()
        points = [[int(e) for e in point.strip().split(" ")]
                  for point in str_points]
        return points

    @staticmethod
    def delete_nearest_point(query_point, points):
        nearest_index, nearest_d = 0, 10000000
        for index in range(len(points)):
            d = (query_point[0] - points[index][0]) ** 2 + \
                (query_point[1] - points[index][1]) ** 2
            if d < nearest_d:
                nearest_d = d
                nearest_index = index
        if nearest_d >= 100:
            return
        del points[nearest_index]

    def load_an_image(self):
        self.current_node = None
        self.current_image = None
        self.show_image = None
        self.current_label_points = list()
        if self.src_stack.size() == 0:  # 所有图片已经处理完毕
            return self.dst_stack.size(), 0
        # 载入一张待处理的图片
        self.current_node = self.src_stack.pop()
        self.current_image = QImage(self.current_node.image_path)
        self.current_label_points = self.read_labeled_points(self.current_node.label_file_path)
        return self.dst_stack.size(), self.src_stack.size() + 1

    def next_image_button_event(self):
        if self.current_node is None:  # 当前没有图片在处理
            return self.dst_stack.size(), 0
        # step 1  保存当前的处理结果
        with open(self.current_node.label_file_path, "w") as label_file:
            for point in self.current_label_points:
                str_line = " ".join([str(e) for e in point]) + "\n"
                label_file.writelines(str_line)
        # step 2  将图片和标注文件剪切到目标文件夹
        self.dst_stack.push(self.current_node)
        # step 3  载入下一张待处理的图片
        return self.load_an_image()

    def previous_image_button_event(self):
        # step 1  先保存当前的处理结果
        if self.current_node is not None:
            with open(self.current_node.label_file_path, "w") as label_file:
                for point in self.current_label_points:
                    str_line = " ".join([str(e) for e in point]) + "\n"
                    label_file.writelines(str_line)
            self.src_stack.push(self.current_node)  # 将图片和标注文件保存回原文件夹
        # step 2  从目标文件夹提取回一张图片至源文件夹中
        if self.dst_stack.size() > 0:
            self.src_stack.push(self.dst_stack.pop())
        # step 3 从源文件夹中提取出一张图片进行处理
        return self.load_an_image()

    def draw_image(self):
        if self.current_image is None:
            return None
        assert isinstance(self.current_image, QImage)
        self.show_image = QImage(self.current_image)
        painter = QPainter()
        painter.begin(self.show_image)
        painter.setBrush(Qt.red)
        for point in self.current_label_points:
            painter.drawEllipse(point[0], point[1], 8, 8)
        painter.end()
        return self.show_image

    def left_mouse_button_event(self, relative_position):
        if self.current_node is None:
            return None
        # step 1  保存当前鼠标左键在图像中点击的位置
        image_width = self.current_image.width()
        image_height = self.current_image.height()
        x = int(image_width * relative_position[0])
        y = int(image_height * relative_position[1])
        self.current_label_points.append([x, y])
        # step 2  在图像中重新绘制所有的标注点
        return self.draw_image()

    def right_mouse_button_event(self, relative_position):
        # step 1  得到当前鼠标右键在图像中点击的位置
        image_width = self.current_image.width()
        image_height = self.current_image.height()
        x = int(image_width * relative_position[0])
        y = int(image_height * relative_position[1])
        # step 2  删除最邻近的点
        if len(self.current_label_points) > 0:
            self.delete_nearest_point((x, y), self.current_label_points)
        # step 2  在图像中重新绘制所有的标注点
        return self.draw_image()
